package ws
//
//import (
//	"blockchain_data/handler/model"
//	"blockchain_data/middleware"
//	"blockchain_data/utils"
//	"bytes"
//	"compress/flate"
//	"encoding/json"
//	"fmt"
//	"github.com/gorilla/websocket"
//	"github.com/sirupsen/logrus"
//	"io/ioutil"
//	"net/http"
//	"reflect"
//	"sync"
//	"time"
//)
//
//
//var log *logrus.Logger
//func init()  {
//	log = middleware.DataLogger()
//}
//type MethonInfo struct {
//	Fun   interface{}
//	Param reflect.Type
//}
//
//func (wsOp *MethonInfo) Init(fun interface{}, param reflect.Type) *MethonInfo {
//	wsOp.Fun = fun
//	wsOp.Param = param
//	return wsOp
//}
//
//type OkWebSocketOp struct {
//	Host string						//根路径
//	Path string						//子路径
//	Conn      *websocket.Conn
//
//	Isclose  bool
//	Reconnect bool
//
//
//	SubStr []byte
//	Fun    interface{}
//	Param  reflect.Type
//	Methon MethonInfo
//
//	ClosePing chan bool
//	ClosePong chan bool
//	PingTime time.Duration
//	Heart bool						//是否需要主动发送心跳
//	StopHeart  chan int
//	Ch chan model.Msg
//
//	Mutex sync.Mutex
//	CloseReadLoop chan bool
//}
//
//func (wsOp *OkWebSocketOp) Open(path string, host string, heart bool,pingTime time.Duration) bool {
//	wsOp.Host = host
//	wsOp.Path = path
//	wsOp.Heart = heart
//	if(wsOp.Heart){
//		wsOp.PingTime = pingTime
//	}
//	wsOp.ClosePing = make(chan bool)
//	wsOp.ClosePong = make(chan bool)
//	wsOp.CloseReadLoop = make(chan bool)
//	wsOp.Reconnect = false
//	ret := wsOp.ConnServer()
//	return ret
//}
//
//func (wsOp *OkWebSocketOp) Close() {
//	wsOp.Isclose = true
//	if wsOp.Conn != nil{
//		wsOp.Conn.Close()
//	}
//	wsOp.Conn = nil
//}
//
//func (wsOp *OkWebSocketOp) ConnServer() bool {
//	// 如果已经再重连，不能在调用
//	if !wsOp.Reconnect {
//		url := fmt.Sprintf("wss://%s%s", wsOp.Host, wsOp.Path)
//		fmt.Println(url)
//		var err error
//		wsOp.Reconnect = true
//		wsOp.Conn, _, err = (&websocket.Dialer{
//			Proxy:            http.ProxyFromEnvironment,
//			HandshakeTimeout: 45 * time.Second,
//		}).Dial(url, nil)
//		time.Sleep(4 * time.Second)
//		if err != nil {
//			log.Errorf("WebSocket 连接错误: %s", err,string(wsOp.SubStr))
//			wsOp.CloseReadLoop <- true
//			wsOp.Reconnect = false
//			wsOp.ConnServer()
//			return false
//		}
//		log.Info("WebSocket 连接成功")
//		wsOp.Reconnect = false
//		go wsOp.ReadLoop()
//
//		if !wsOp.Isclose && len(wsOp.SubStr) != 0{
//			wsOp.Sub(wsOp.SubStr,wsOp.Fun,wsOp.Param)
//		}
//		wsOp.Conn.SetCloseHandler(wsOp.OnClose)
//
//		return true
//	}else {
//		return false
//	}
//
//}
//
//func (wsOp *OkWebSocketOp) OnClose(code int, text string) error {
//	wsOp.Conn = nil
//	fmt.Println("OnClose重新连接",string(wsOp.SubStr))
//	wsOp.CloseReadLoop <- true
//	go wsOp.ConnServer()
//	return fmt.Errorf("WebSocket 异常断开，尝试重新连接。。。")
//}
//
//
//
//// HeartWork 需要主动发心跳的work
//func (wsOp *OkWebSocketOp)HeartWork()  {
//	log.Info("HeartWork 进入")
//	//每20秒发一次ping
//	ticker := time.NewTicker(wsOp.PingTime)
//	defer ticker.Stop()
//	for {
//		select {
//		case <-ticker.C:
//			if wsOp.Conn != nil && !wsOp.Isclose {
//				wsOp.Ping()
//			}
//		case <-wsOp.ClosePing:
//			log.Info("HeartWork 退出")
//			return
//		}
//	}
//}
//
//
//
//// Ping 如果有需要主动发送心跳重写
//func (wsOp *OkWebSocketOp) Ping()  {
//	msg := "ping"
//	//log.Printf("Send Msg: %s", msg)
//	if wsOp.Conn != nil {
//		wsOp.Mutex.Lock()
//		wsOp.Conn.WriteMessage(websocket.TextMessage, []byte(msg))
//		wsOp.Mutex.Unlock()
//		go wsOp.Pong()
//	}
//}
//
//// Pong 响应
//func (wsOp *OkWebSocketOp) Pong()  {
//	log.Info("pong 进入",string(wsOp.SubStr))
//	//如果20秒内没有pong就重新连接
//	ticker := time.NewTicker(wsOp.PingTime - 2 * time.Second)
//	defer ticker.Stop()
//	select {
//	case <-ticker.C:
//		log.Error("pong主动重连",string(wsOp.SubStr))
//		wsOp.Conn = nil
//		wsOp.ClosePing <- true
//		wsOp.CloseReadLoop <- true
//		go wsOp.ConnServer()
//		log.Info("pong ticker 退出",string(wsOp.SubStr))
//		return
//	case <-wsOp.ClosePong:
//		log.Info("pong ClosePong 退出")
//		return
//	}
//}
//
//func (wsOp *OkWebSocketOp) ReadLoop() {
//	for {
//		select {
//		case <-wsOp.CloseReadLoop:
//			log.Info("ReadLoop已经退出")
//			return
//		default:
//			if  wsOp.Conn != nil{
//				//log.Info("进入ReadLoop",string(wsOp.SubStr))
//				messageType, message, err := wsOp.Conn.ReadMessage()
//				if err != nil && !wsOp.Isclose{
//					log.Error("ReadLoop",err)
//					return
//				}
//				txtMsg := message
//				switch messageType {
//				case websocket.TextMessage:
//				case websocket.BinaryMessage:
//					txtMsg, err = wsOp.GzipDecode(message)
//				}
//				var jdata map[string]interface{}
//				if string(txtMsg) == "pong" {
//					log.Info("返回pong",string(wsOp.SubStr))
//					pong := wsOp.ClosePong
//					pong <- true
//				}else {
//					err = json.Unmarshal([]byte(message), &jdata)
//					if err != nil {
//						log.Errorf("msg to map[string]json.RawMessage error: %s", err)
//						continue
//					}
//					if _, found := jdata["data"]; found{
//						wsOp.HandleSubCallbackFun(string(txtMsg))
//					}else {
//						myMsg := &model.Msg{}
//						err = utils.JsonBytes2Struct(txtMsg, myMsg)
//						if err == nil {
//							if myMsg.Event != "error"{
//								wsOp.Ch <- model.Msg{Event: "success",Msg: "订阅成功"}
//								//记录信息
//								log.Info(string(message))
//							}else {
//								wsOp.Ch <- model.Msg{Event: "error",Msg: "订阅失败"}
//								//记录信息
//								log.Errorf(string(message))
//							}
//						}else {
//							wsOp.Ch <- model.Msg{Event: "error",Msg: "订阅失败"}
//							log.Errorf(string(message))
//						}
//					}
//				}
//			}
//		}
//	}
//}
//
//func (wsOp *OkWebSocketOp) HandleSubCallbackFun(data string) {
//	var mi *MethonInfo = nil
//	mi = new(MethonInfo).Init(wsOp.Fun, wsOp.Param)
//
//	wsOp.RunFunction(mi, data)
//}
//
//func (wsOp *OkWebSocketOp) RunFunction(mi *MethonInfo, data string) {
//	param := reflect.New(mi.Param).Interface()
//	json.Unmarshal([]byte(data), &param)
//
//	rargs := make([]reflect.Value, 1)
//
//	rargs[0] = reflect.ValueOf(param)
//	fun := reflect.ValueOf(mi.Fun)
//	fun.Call(rargs)
//}
//
//func (wsOp *OkWebSocketOp) Sub(subStr []byte, fun interface{}, param reflect.Type) bool {
//	wsOp.SubStr = subStr
//	wsOp.Fun = fun
//	wsOp.Param = param
//	wsOp.Mutex.Lock()
//	err := wsOp.Conn.WriteMessage(websocket.TextMessage, subStr)
//	wsOp.Mutex.Unlock()
//	if err != nil{
//		log.Error(err)
//	}else {
//		log.Info("WebSocket 订阅成功",string(wsOp.SubStr))
//	}
//	//订阅成功才能心跳
//	if(wsOp.Heart){
//		go wsOp.HeartWork()
//	}
//	return true
//}
//
//func (wsOp *OkWebSocketOp) Unsub(unsubStr []byte) bool {
//	wsOp.Mutex.Lock()
//	wsOp.Conn.WriteMessage(websocket.TextMessage, unsubStr)
//	wsOp.Mutex.Unlock()
//	return true
//}
//
//func (wsOp *OkWebSocketOp) GzipDecode(in []byte) ([]byte, error) {
//	reader := flate.NewReader(bytes.NewReader(in))
//	defer reader.Close()
//
//	return ioutil.ReadAll(reader)
//}
//
